package com.museum.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.museum.common.Result;
import com.museum.entity.Reservation;
import com.museum.entity.User;
import com.museum.entity.SystemSettings;
import com.museum.service.ReservationService;
import com.museum.service.UserService;
import com.museum.service.SystemSettingsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/reservation")
public class ReservationController {

    private static final Logger log = LoggerFactory.getLogger(ReservationController.class);

    @Autowired
    private ReservationService reservationService;

    @Autowired
    private UserService userService;

    @Autowired
    private SystemSettingsService systemSettingsService;

    @GetMapping("/admin/list")
    public Result<Page<Reservation>> adminList(
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "size", defaultValue = "10") Integer size,
            @RequestParam(value = "status", required = false) Integer status,
            @RequestParam(value = "date", required = false) String date) {
        Page<Reservation> pageParam = new Page<>(page, size);
        Page<Reservation> result = reservationService.pageList(pageParam, status, date);
        return Result.success(result);
    }

    @GetMapping("/my")
    public Result<List<Reservation>> myReservations(@RequestParam("userId") Long userId) {
        List<Reservation> list = reservationService.getUserReservations(userId);
        return Result.success(list);
    }

    /**
     * 获取预约详情
     * @param id 预约ID
     * @return 预约详情
     */
    @GetMapping("/detail/{id}")
    public Result<Map<String, Object>> getDetail(@PathVariable Long id) {
        Reservation reservation = reservationService.getById(id);
        if (reservation == null) {
            return Result.error("预约不存在");
        }
        
        // 构建详情数据
        Map<String, Object> detailMap = new HashMap<>();
        detailMap.put("id", reservation.getId());
        detailMap.put("userId", reservation.getUserId());
        detailMap.put("visitor_count", reservation.getVisitorCount());
        detailMap.put("visit_date", reservation.getVisitDate());
        detailMap.put("visit_time_slot", reservation.getVisitTimeSlot());
        detailMap.put("status", reservation.getStatus());
        detailMap.put("create_time", reservation.getCreateTime());
        
        // 获取用户信息
        User user = userService.getById(reservation.getUserId());
        if (user != null) {
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put("id", user.getId());
            userInfo.put("nickname", user.getNickname());
            userInfo.put("phone", user.getPhone());
            userInfo.put("avatar", user.getAvatar());
            detailMap.put("user_info", userInfo);
        }
        
        // 获取博物馆信息
        SystemSettings settings = systemSettingsService.getSettings();
        if (settings != null) {
            Map<String, Object> museumInfo = new HashMap<>();
            museumInfo.put("name", settings.getMuseumName());
            museumInfo.put("address", settings.getAddress());
            museumInfo.put("openTime", settings.getOpenTime());
            detailMap.put("museum_info", museumInfo);
        }
        
        return Result.success(detailMap);
    }

    /**
     * 提交预约（会减少对应日期的可用票数）
     */
    @PostMapping("/submit")
    public Result<Reservation> submit(@RequestBody Map<String, Object> requestData) {
        try {
            // 从请求数据中提取预约信息
            Reservation reservation = new Reservation();
            reservation.setUserId(Long.valueOf(requestData.get("userId").toString()));
            reservation.setVisitorCount(Integer.valueOf(requestData.get("visitorCount").toString()));
            reservation.setVisitDate(requestData.get("visitDate").toString());
            reservation.setVisitTimeSlot(requestData.get("visitTimeSlot").toString());
            reservation.setStatus(0); // 0-待审核
            reservation.setCreateTime(LocalDateTime.now());
            reservation.setUpdateTime(LocalDateTime.now());
            
            // 检查票数是否足够
            Integer availableCount = reservationService.getAvailableTickets(reservation.getVisitDate());
            
            if (availableCount < reservation.getVisitorCount()) {
                return Result.error("所选日期票数不足，剩余票数：" + availableCount);
            }
            
            // 获取访客ID列表
            List<Long> visitorIds = null;
            if (requestData.get("visitors") != null) {
                visitorIds = ((List<Integer>) requestData.get("visitors"))
                    .stream()
                    .map(Long::valueOf)
                    .collect(Collectors.toList());
            }
            
            // 保存预约并减少票数，同时关联访客
            boolean success = reservationService.saveWithVisitors(reservation, visitorIds);
            if (!success) {
                return Result.error("预约失败，请稍后重试");
            }
            
            return Result.success(reservation);
        } catch (Exception e) {
            log.error("提交预约异常", e);
            return Result.error("预约失败，请稍后重试");
        }
    }

    @PutMapping("/status/{id}")
    public Result<Boolean> updateStatus(
            @PathVariable Long id,
            @RequestParam Integer status) {
        boolean success = reservationService.updateStatus(id, status);
        if (!success) {
            return Result.error("操作失败");
        }
        return Result.success(true);
    }

    /**
     * 取消预约（会恢复对应日期的票数）
     */
    @PostMapping("/cancel/{id}")
    public Result<Boolean> cancel(@PathVariable Long id) {
        boolean success = reservationService.cancelAndRestoreTickets(id);
        if (!success) {
            return Result.error("取消失败");
        }
        return Result.success(true);
    }
    
    /**
     * 获取时间段
     */
    @GetMapping("/timeslots")
    public Result<List<Map<String, Object>>> getTimeSlots(@RequestParam("date") String date) {
        List<Map<String, Object>> timeSlots = reservationService.getAvailableTimeSlots(date);
        return Result.success(timeSlots);
    }
    
    /**
     * 获取指定日期范围内的票务可用情况
     */
    @GetMapping("/availability")
    public Result<Map<String, Integer>> getAvailability(
            @RequestParam("startDate") String startDate,
            @RequestParam("endDate") String endDate) {
        Map<String, Integer> availability = reservationService.getTicketAvailability(startDate, endDate);
        return Result.success(availability);
    }
    
    /**
     * 获取单个日期的票务可用情况
     */
    @GetMapping("/ticket-count")
    public Result<Integer> getTicketCount(@RequestParam("date") String date) {
        Integer count = reservationService.getAvailableTickets(date);
        return Result.success(count);
    }
    
    /**
     * 获取票务可用性信息，包含未来30天的可用日期和每个日期的可用票数
     * 前端可用于预约日历展示
     */
    @GetMapping("/ticket-availability")
    public Result<Map<String, Object>> getTicketAvailability() {
        try {
            // 计算当前日期和未来30天的日期范围
            LocalDate today = LocalDate.now();
            LocalDate endDate = today.plusDays(30);
            
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String startDateStr = today.format(formatter);
            String endDateStr = endDate.format(formatter);
            
            // 获取日期范围内的票务可用情况
            Map<String, Integer> availabilityMap = reservationService.getTicketAvailability(startDateStr, endDateStr);
            
            // 获取系统设置中的每日最大预约数
            SystemSettings settings = systemSettingsService.getSettings();
            int maxDailyReservation = settings != null && settings.getMaxReservation() != null ? 
                    settings.getMaxReservation() : 200;
            
            // 构建结果
            Map<String, Object> result = new HashMap<>();
            result.put("maxDailyReservation", maxDailyReservation);
            result.put("availableDates", availabilityMap);
            
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取票务可用性信息失败", e);
            return Result.error("获取票务可用性信息失败");
        }
    }

    /**
     * 删除预约记录（仅对已失效的预约）
     */
    @DeleteMapping("/delete/{id}")
    public Result<Boolean> deleteReservation(@PathVariable Long id) {
        // 获取预约信息
        Reservation reservation = reservationService.getById(id);
        if (reservation == null) {
            return Result.error("预约不存在");
        }
        
        // 验证状态是否为已失效(2)
        if (reservation.getStatus() != 2) {
            return Result.error("只能删除已失效的预约");
        }
        
        // 执行删除
        boolean success = reservationService.removeById(id);
        if (!success) {
            return Result.error("删除失败");
        }
        
        return Result.success(true);
    }
    
    /**
     * 获取预约关联的观众详细信息
     * @param id 预约ID
     * @return 观众详细信息列表
     */
    @GetMapping("/visitors-detail/{id}")
    public Result<List<Map<String, Object>>> getVisitorsDetail(@PathVariable Long id) {
        try {
            // 获取预约信息
            Reservation reservation = reservationService.getById(id);
            if (reservation == null) {
                return Result.error("预约不存在");
            }
            
            // 获取预约关联的观众信息
            List<Map<String, Object>> visitorsList = reservationService.getReservationVisitorsDetail(id);
            
            if (visitorsList == null) {
                visitorsList = new ArrayList<>();
            }
            
            return Result.success(visitorsList);
        } catch (Exception e) {
            log.error("获取预约观众详情失败", e);
            return Result.error("获取预约观众详情失败");
        }
    }
    
    /**
     * 更新预约信息
     * @param requestData 请求数据，包含预约信息和观众ID列表
     * @return 更新结果
     */
    @PutMapping("/update")
    public Result<Boolean> updateReservation(@RequestBody Map<String, Object> requestData) {
        try {
            log.info("更新预约请求: {}", requestData);
            
            // 从请求数据中提取ID
            Long id = Long.valueOf(requestData.get("id").toString());
            
            // 获取当前预约信息
            Reservation existingReservation = reservationService.getById(id);
            if (existingReservation == null) {
                return Result.error("预约不存在");
            }
            
            // 只允许修改待审核的预约
            if (existingReservation.getStatus() != 0) {
                return Result.error("只能修改待审核的预约");
            }
            
            // 保存原始预约人数和日期，用于票数调整
            int originalVisitorCount = existingReservation.getVisitorCount();
            String originalVisitDate = existingReservation.getVisitDate();
            
            // 更新预约信息
            existingReservation.setUserId(Long.valueOf(requestData.get("userId").toString()));
            existingReservation.setVisitorCount(Integer.valueOf(requestData.get("visitorCount").toString()));
            existingReservation.setVisitDate(requestData.get("visitDate").toString());
            existingReservation.setVisitTimeSlot(requestData.get("visitTimeSlot").toString());
            existingReservation.setUpdateTime(LocalDateTime.now());
            
            // 日期或人数变化，需要调整票数
            boolean needAdjustTickets = !originalVisitDate.equals(existingReservation.getVisitDate()) 
                    || originalVisitorCount != existingReservation.getVisitorCount();
            
            // 如果日期变化，检查新日期票数是否足够
            if (needAdjustTickets) {
                // 如果日期变化，需要先恢复原日期的票数，再检查新日期的票数是否够用
                if (!originalVisitDate.equals(existingReservation.getVisitDate())) {
                    // 恢复原日期的票数
                    reservationService.restoreTickets(originalVisitDate, originalVisitorCount);
                    
                    // 检查新日期票数是否足够
                    Integer availableCount = reservationService.getAvailableTickets(existingReservation.getVisitDate());
                    if (availableCount < existingReservation.getVisitorCount()) {
                        // 恢复原日期的票数扣减
                        reservationService.reduceTickets(originalVisitDate, originalVisitorCount);
                        return Result.error("所选日期票数不足，剩余票数：" + availableCount);
                    }
                    
                    // 减少新日期的票数
                    reservationService.reduceTickets(existingReservation.getVisitDate(), existingReservation.getVisitorCount());
                } else if (originalVisitorCount != existingReservation.getVisitorCount()) {
                    // 仅人数变化，但日期相同
                    if (originalVisitorCount < existingReservation.getVisitorCount()) {
                        // 人数增加，检查票数是否够用
                        Integer availableCount = reservationService.getAvailableTickets(existingReservation.getVisitDate());
                        int additionalCount = existingReservation.getVisitorCount() - originalVisitorCount;
                        
                        if (availableCount < additionalCount) {
                            return Result.error("所选日期票数不足，剩余票数：" + availableCount);
                        }
                        
                        // 减少额外需要的票数
                        reservationService.reduceTickets(existingReservation.getVisitDate(), additionalCount);
                    } else {
                        // 人数减少，恢复多余的票数
                        int reducedCount = originalVisitorCount - existingReservation.getVisitorCount();
                        reservationService.restoreTickets(existingReservation.getVisitDate(), reducedCount);
                    }
                }
            }
            
            // 获取访客ID列表
            List<Long> visitorIds = null;
            if (requestData.get("visitors") != null) {
                visitorIds = ((List<Integer>) requestData.get("visitors"))
                    .stream()
                    .map(Long::valueOf)
                    .collect(Collectors.toList());
            }
            
            // 更新预约信息和关联的访客
            boolean success = reservationService.updateWithVisitors(existingReservation, visitorIds);
            if (!success) {
                // 如果更新失败，需要恢复票数变化
                if (needAdjustTickets) {
                    if (!originalVisitDate.equals(existingReservation.getVisitDate())) {
                        // 恢复新日期的票数
                        reservationService.restoreTickets(existingReservation.getVisitDate(), existingReservation.getVisitorCount());
                        // 减少原日期的票数
                        reservationService.reduceTickets(originalVisitDate, originalVisitorCount);
                    } else if (originalVisitorCount != existingReservation.getVisitorCount()) {
                        if (originalVisitorCount < existingReservation.getVisitorCount()) {
                            // 恢复多扣的票数
                            int additionalCount = existingReservation.getVisitorCount() - originalVisitorCount;
                            reservationService.restoreTickets(existingReservation.getVisitDate(), additionalCount);
                        } else {
                            // 重新减少原本的票数
                            int reducedCount = originalVisitorCount - existingReservation.getVisitorCount();
                            reservationService.reduceTickets(existingReservation.getVisitDate(), reducedCount);
                        }
                    }
                }
                
                return Result.error("更新预约失败，请稍后重试");
            }
            
            return Result.success(true);
        } catch (Exception e) {
            log.error("更新预约异常", e);
            return Result.error("更新预约失败：" + e.getMessage());
        }
    }
} 